@node Dynamic loading of C modules
@section Dynamic loading of C modules

@cindex C dynamic loading
@cindex C shared objects
@stindex load-dynamic-externals
External code can be loaded into a running Scheme48 on most Unices and
on Windows.  Such external code must be stored in shared objects; see
below on details of the C side.  The relevant Scheme procedures are
available in the @code{load-dynamic-externals} structure:

@deffn procedure load-dynamic-externals filename add-file-type? reload-on-repeat? reload-on-resume? @returns{} dynamic-externals
@deffnx procedure import-dynamic-externals filename @returns dynamic-externals
@deffnx procedure unload-dynamic-externals dynamic-externals @returns{} unspecified
@code{Load-dynamic-external} loads a shared object from
@var{filename}, with an appropriate file type appended if
@var{add-file-type?} is true (@code{.so} on Unix and @code{.dll} on
Windows), and returns a @dfn{dynamic externals} object representing
the loaded shared object.  If the shared object was already loaded,
then if @var{reload-on-repeat?} is true, it is reloaded; otherwise,
the @code{load-dynamic-externals} call has no effect.  If the dynamic
externals descriptor is stored in a dumped heap image, when that heap
image is resumed, if @code{reload-on-resume?} is true, the shared
object corresponding with that dynamic external descriptor is
reloaded.  @code{Unload-dynamic-externals} unloads the given dynamic
externals object.

@code{Import-dynamic-externals} is a convenient wrapper for the common
case of @code{load-dynamic-externals}; it is equivalent to
@code{(load-dynamic-externals #t #f #t)}, @ie{} it will append a file
type, it will not reload the shared object if it was already loaded,
and the shared object will be loaded if part of a resumed heap image.
@end deffn

@deffn procedure reload-dynamic-externals filename @returns{} unspecified
Reloads the shared object named by @var{filename}.  This is intended
as an interactive utility, which is why it accepts the filename of the
shared object and not a dynamic externals descriptor.
@end deffn

Shared objects intended to be loaded into Scheme48 must define two
functions:

@deftypefn {C function} void s48_on_load (void)
@deftypefnx {C function} void s48_on_reload (void)
@code{s48_on_load} is called when the shared object is initially
loaded by Scheme48.  It typically consists of a number of invocations
of @code{S48_EXPORT_FUNCTION} to make C functions available to
Scheme48 code.  @code{s48_on_reload} is called when the shared object
is reloaded after it has been initially loaded once; it typically just
calls @code{s48_on_load}, but it may perform other reinitializations.
@end deftypefn

On Linux, the following commands compile the C source file
@file{foo.c} into a shared object @file{foo.so} that can be loaded
dynamically by Scheme48:

@example
% gcc -c -o foo.o foo.c
% ld -shared -o foo.so foo.o@end example

@subsection Old dynamic loading interface

The old @code{dynamic-externals} structures, which exported
@code{dynamic-load}, @code{get-external}, @code{lookup-external},
@code{lookup-all-externals}, @code{external?}, @code{external-name},
@code{external-value}, and @code{call-external}, is still supported,
but it will not work on Windows, its use is deprecated, and it is
likely to vanish in a future release.  The old documentation is
preserved to aid updating of old code:

@stindex dynamic-externals
On architectures that support it, external code can be loaded into a
running Scheme48 process, and C object file bindings can be accessed
at runtime & their values called.  These Scheme procedures are exported
by the structure @code{dynamic-externals}.

In some Unices, retrieving a value from the current process may require
a non-trivial amount of computation.  We recommend that a dynamically
loaded file contain a single initialization function that creates
shared bindings for the values exported by the file.

@deffn {Scheme procedure} dynamic-load string @returns{} unspecified
Loads the filename named by @var{string} into the current process.
An exception is raised if the file cannot be found or if dynamic
loading is not supported by the host operating system.  The file must
have been compiled & linked appropriately.  For Linux, for example,
the following commands compile @file{foo.c} into a file @file{foo.so}
that can be loaded dynamically:

@example
% gcc -c -o foo.o foo.c
% ld -shared -o foo.so foo.o@end example
@end deffn

@deffn {Scheme procedure} get-external string @returns{} external
@deffnx {Scheme procedure} external? object @returns{} boolean
@deffnx {Scheme procedure} external-name external @returns{} string
@deffnx {Scheme procedure} external-value external @returns{} byte-vector
These procedures access external values bound in the current process.
@code{Get-external} returns a @dfn{external} object that contains the
value of the C binding with the name @var{string}.  It signals a
warning if there is no such binding in the current process.
@code{External?} is the disjoint type predicate for externals, and
@code{external-name} & @code{external-value} return the name & value of
an external.  The value is represented as a @embedref{Bitwise
manipulation,byte vector} of length four on 32-bit architectures.  The
value is that of the C binding from when @code{get-external} (or
@code{lookup-external}, as described below) was called.
@end deffn

@deffn {Scheme procedure} lookup-external external @returns{} boolean
@deffnx {Scheme procedure} lookup-all-externals @returns{} boolean
@code{Lookup-external} updates the value of @var{external} by looking
up its binding in the current process.  It returns @code{#t} if the
external is bound and @code{#f} if not.  @code{Lookup-all-externals}
calls @code{lookup-external} on all externals in the current Scheme48
image.  It returns @code{#t} if all were bound and @code{#f} if there
was at least one unbound external.
@end deffn

@deffn {Scheme procedure} call-external external argument @dots{} @returns{} value
Calls the C function pointed to by @var{external} with the given
arguments, and returns the value that the C function returned.  This
is like @code{call-imported-binding} and @code{call-external-value}
except that the function argument is represented as an external, not as
an imported binding or byte vector containing a pointer.  For more
details, @pxref{Calling C functions from Scheme}.
@end deffn
